﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;

namespace IceZero.Common.Services
{
    /// <summary>
    /// 在线容器对象
    /// </summary>
    public class OnlineContainer
    {
        /// <summary>
        /// 存放数据的对象
        /// </summary>
        private static ConcurrentDictionary<string, ConcurrentDictionary<string, OnlineObject>> _onlineSets
            = new ConcurrentDictionary<string, ConcurrentDictionary<string, OnlineObject>>();
        private static OnlineContainer _default;
        /// <summary>
        /// 默认实现对象
        /// </summary>
        public static OnlineContainer Default
        {
            get
            {
                if (_default == null)
                {
                    _default = new OnlineContainer();
                }
                return _default;
            }
        }
        /// <summary>
        /// 当前实例的定时器
        /// </summary>
        public Timer Timer { get; set; }

        public OnlineContainer()
        {
            Timer = new Timer()
            {
                Enabled = true,
                AutoReset = true,
                Interval = 2000,//2s
            };
            Timer.Elapsed += Timer_Elapsed;
            Timer.Start();
        }

        private void Timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            var sb = new StringBuilder();
            sb.AppendLine($"area count:{_onlineSets.Count}");
            foreach (var areaItem in _onlineSets)
            {
                sb.AppendLine($"area [{areaItem.Key}] key count:{areaItem.Value.Count}");
                foreach (var keyItem in areaItem.Value)
                {
                    if (keyItem.Value.ExpireTime < DateTime.Now)
                    {
                        areaItem.Value.TryRemove(keyItem);
                    }
                    sb.AppendLine($"key {keyItem.Key} info , data info:{keyItem.Value.CreateTime}:{keyItem.Value.ExpireTime}");
                }
            }
            Console.WriteLine(sb.ToString());
        }

        /// <summary>
        /// 添加在线对象
        /// </summary>
        /// <param name="area">区域名，用于区分不同的数据</param>
        /// <param name="key">键</param>
        /// <param name="data">数据</param>
        /// <param name="expireTime">过期时间，过期时间不能设定太久，自行控制</param>
        public void Add(string area, string key, Dictionary<string, string> data, DateTime expireTime)
        {
            if (!_onlineSets.ContainsKey(area))
            {
                _onlineSets.TryAdd(area, new ConcurrentDictionary<string, OnlineObject>());
            }
            if (_onlineSets[area].ContainsKey(key))
            {
                _onlineSets[area].TryRemove(key, out _);
            }
            _onlineSets[area].TryAdd(key, new OnlineObject()
            {
                CreateTime = DateTime.Now,
                ExpireTime = expireTime,
                Data = data
            });
        }

        /// <summary>
        /// 主动删除区域内所有对象
        /// </summary>
        /// <param name="area">区域名</param>
        /// <returns></returns>
        public bool Delete(string area)
        {
            if (!_onlineSets.ContainsKey(area))
            {
                return false;
            }
            return _onlineSets.TryRemove(area, out _);
        }
        /// <summary>
        /// 删除域内某个key的对象
        /// </summary>
        /// <param name="area">区域名</param>
        /// <param name="key">键</param>
        /// <returns></returns>
        public bool Delete(string area, string key)
        {
            if (!_onlineSets.ContainsKey(area))
            {
                return false;
            }
            if (!_onlineSets[area].ContainsKey(key))
            {
                return false;
            }
            return _onlineSets[area].TryRemove(key, out _);
        }

        /// <summary>
        /// 获取域里面的某个键的对象
        /// </summary>
        /// <param name="area">区域名</param>
        /// <param name="key">键</param>
        public OnlineObject Get(string area, string key)
        {
            if (!_onlineSets.ContainsKey(area))
            {
                return null;
            }
            if (!_onlineSets[area].ContainsKey(key))
            {
                return null;
            }
            return _onlineSets[area][key];
        }
        /// <summary>
        /// 获取域里面的所有的对象
        /// </summary>
        /// <param name="area">区域名</param>
        /// <returns></returns>
        public ConcurrentDictionary<string, OnlineObject> GetAll(string area)
        {
            if (!_onlineSets.ContainsKey(area))
            {
                return null;
            }
            return _onlineSets[area];
        }
    }
}
